home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-07-20 | 11.9 KB | 417 lines | [TEXT/CWIE] |
- /*******************************************************************************\
- | |
- | HCmdButtonAttachment.cp ©1997 John C. Daub. All rights reserved. |
- | |
- | See the file "HCmdButtonAttachment README" for full details, instructions, |
- | changes, licensing agreement, etc. Due to the important information |
- | included in that file, if you did not receive a copy of it, please contact |
- | the author for a copy immediately, before using this code. |
- | |
- | John C. Daub <mailto:hsoi@eden.com> |
- | <http://www.eden.com/~hsoi/> <http://www.eden.com/~hsoi/prog.html> |
- | |
- \*******************************************************************************/
-
-
- #ifdef PowerPlant_PCH
- #include PowerPlant_PCH
- #endif
-
-
- #include "HCmdButtonAttachment.h"
-
- #include <PP_KeyCodes.h>
- #include <LView.h>
-
- #ifndef __EVENTS__
- #include <Events.h>
- #endif
-
- #ifndef __CONTROLS__
- #include <Controls.h>
- #endif
-
- #ifndef __TEXTUTILS__
- #include <TextUtils.h>
- #endif
-
-
- #if ( __PowerPlant__ < 0x01608000 ) // version 1.6/CW11
-
- //=============================================================================
- // • CreateFromStream [static, public]
- //=============================================================================
- // Used when registering the class. Obsolete in more recent versions of
- // PowerPlant, so we conditionally compile it in and out. If you are using
- // PowerPlant 1.6 (CW11) or higher, you should use the RegisterClass_() macro
- // instead to register your classes.
-
- HCmdButtonAttachment*
- HCmdButtonAttachment::CreateFromStream(
- LStream *inStream )
- {
- return (new HCmdButtonAttachment(inStream));
- }
-
- #endif
-
-
- //=============================================================================
- // • HCmdButtonAttachment [public]
- //=============================================================================
- // Parameterized constructor
-
- HCmdButtonAttachment::HCmdButtonAttachment(
- PaneIDT inControlID,
- Uchar inSpecifiedKey,
- Uint32 inDelay,
- Boolean inDrawShortcut,
- MessageT inMessage,
- Boolean inExecuteHost)
- : LAttachment( inMessage, inExecuteHost ),
- mControl(nil),
- mControlID(inControlID),
- mDrawShortcut(inDrawShortcut),
- mUseSpecifiedKey(inSpecifiedKey != 0), // if you specify a key, we'll assume you want
- // to use that key. if you want to use the
- // first letter of the control's descriptor,
- // assign zero to inSpecifiedKey
- mSpecifiedKey(inSpecifiedKey),
- mFlipped(false),
- mOriginalTitle("\p"),
- mMungedTitle("\p"),
- // mWhenToDraw(0), // only usefully initialized at the end of the
- // init routine, so skip it here and save some
- // code size.
- mDelay(inDelay)
- {
- InitCmdButtonAttachment();
- }
-
-
- //=============================================================================
- // • HCmdButtonAttachment [public]
- //=============================================================================
- // LStream constructor
-
- HCmdButtonAttachment::HCmdButtonAttachment(
- LStream *inStream )
- : LAttachment(inStream),
- mControl(nil),
- mFlipped(false),
- mOriginalTitle("\p"),
- mMungedTitle("\p")
- // mWhenToDraw(0) // see above comment for why we don't init this
- {
- inStream->ReadData( &mControlID, sizeof(mControlID) );
-
- inStream->ReadData( &mUseSpecifiedKey, sizeof(mUseSpecifiedKey) );
-
- // for ease of editing in Constructor, the "Specified key" field
- // is a string of length 1, but since it's a Pascal-style string,
- // 2 bytes are actually stored. So, we'll read and swallow one dummy
- // character for the length byte.
-
- Uchar dummy;
- inStream->ReadData( &dummy, 1 );
- SignalIf_(dummy == 0); // if the string is zero length, that's bad
- inStream->ReadData( &mSpecifiedKey, sizeof(mSpecifiedKey) );
-
- inStream->ReadData( &mDelay, sizeof(mDelay) );
- inStream->ReadData( &mDrawShortcut, sizeof(mDrawShortcut) );
-
- InitCmdButtonAttachment();
- }
-
-
- //=============================================================================
- // • ~HCmdButtonAttachment [public, virtual]
- //=============================================================================
- // Destructor
-
- HCmdButtonAttachment::~HCmdButtonAttachment()
- {
- // nothing
- }
-
-
- //=============================================================================
- // • InitCmdButtonAttachment [private]
- //=============================================================================
- // Private initializer
-
- void
- HCmdButtonAttachment::InitCmdButtonAttachment()
- {
- // see who we are attached to
-
- LView *theView = dynamic_cast<LView*>(mOwnerHost);
-
- // normally I would check for nil here, but it might be a legal
- // situation.... so we'll contend with it in other ways...
-
- if ( theView != nil ) {
-
- // get the control and save it for later (faster to cache this
- // pointer than to call FindPaneByID() all the time)
-
- SetControl( dynamic_cast<LControl*>(theView->FindPaneByID(GetControlPaneID())) );
-
- // again, no check for nil here... we have other ways.
- }
-
- // get the original control title
-
- if ( (GetControl() != nil) && GetDrawShortcut() ) {
- Str255 theTitle;
- GetControl()->GetDescriptor(theTitle);
- SetOriginalTitle(theTitle);
- }
-
- SetWhenToDraw();
-
- // we only need to repeat if we're going to draw or not
-
- if (GetDrawShortcut()) {
- StartRepeating();
- }
- }
-
-
- //=============================================================================
- // • ExecuteSelf [protected, virtual]
- //=============================================================================
- // Does the dirty work of making the "click" happen
-
- void
- HCmdButtonAttachment::ExecuteSelf(
- MessageT inMessage,
- void *ioParam )
- {
- #pragma unused (inMessage)
-
- // here's one way we deal with nil pointers
-
- if ( GetControl() == nil ) {
- InitCmdButtonAttachment();
- }
-
- // and now we hope we have something...
-
- if ( GetControl() != nil ) {
-
- // get the EventRecord
- EventRecord theMacEvent = (*(EventRecord*)ioParam);
-
- // we only need worry if the cmdKey is held down
-
- if ( theMacEvent.modifiers & cmdKey ) {
-
- // find our our hot key. we want to do this every time (instead of
- // just caching it) because titles could change on the fly, so we should
- // be responsive.
-
- Uchar theHotKey = FindHotKey();
-
- // get the key pressed
-
- Uint8 theKeyPress = theMacEvent.message & charCodeMask;
-
- // see if things match up
- if ( LString::CompareIgnoringCase( &theHotKey, &theKeyPress, 1, 1 ) == 0 ) {
-
- // we have a winner, so fake the click in the button
-
- GetControl()->SimulateHotSpotClick(kControlButtonPart);
- }
- }
- }
- }
-
-
- //=============================================================================
- // • SpendTime [public, virtual]
- //=============================================================================
- // Used to modify the look of the control title, appending the cmd-key
- // shortcut to the title of the control
-
- void
- HCmdButtonAttachment::SpendTime(
- const EventRecord &inMacEvent )
- {
- #pragma unused(inMacEvent)
-
- // have to put checks in here, lest risk crashing....
-
- if ( GetControl() == nil ) {
- InitCmdButtonAttachment();
- }
-
- if ( GetControl() == nil ) {
- return;
- }
-
- // we'll only do this if we're enabled (and visble), active, and if the cmd-key is
- // held down (this helps prevent modifying a control that wouldn't make sense
- // to modify (e.g. disabled), and also keeps controls in a not-active state
- // (e.g. backgrounded) from being modified)
-
- LControl *theControl = GetControl();
-
- if ( theControl->IsEnabled() &&
- theControl->IsActive() &&
- IsCommandKeyPressed() ) {
-
- // modify the title to have the shortcut appended to it
-
- Uchar theHotKey = FindHotKey();
- MungeTitle( theHotKey );
-
- // and if we already displaying the munged title, don't switch it
- // again, to reduce flicker
-
- if ( !GetShowKeyEquiv() ) {
- Str255 theTitle;
- GetMungedTitle(theTitle);
- theControl->SetDescriptor( theTitle );
- SetShowKeyEquiv( true );
- }
-
- } else {
-
- // no cmd-key down, ensure we're looking normal. and again, only
- // do this if we need to, to reduce flicker
-
- if ( GetShowKeyEquiv() ) {
- Str255 theTitle;
- GetOriginalTitle( theTitle );
- theControl->SetDescriptor( theTitle );
- SetShowKeyEquiv( false );
- }
- }
- }
-
-
- //=============================================================================
- // • IsCommandKeyPressed [public, virtual]
- //=============================================================================
- // Looks to see if the command key is held down or not. We have to use
- // GetKeys() to do this as modifiers don't generate events
-
- Boolean
- HCmdButtonAttachment::IsCommandKeyPressed()
- {
- // get the state of the keyboard
-
- KeyMap theKeyMap;
- ::GetKeys(theKeyMap);
-
- // see if the command key is held down
-
- if (((Uchar*)theKeyMap)[6] & 0x80) {
-
- // if so, make sure we don't draw until mDelay has passed
-
- if ( ::TickCount() >= GetWhenToDraw() ) {
- return true;
- } else {
- return false;
- }
- } else {
-
- // it's not held down, so keep upping the ante on when to
- // draw so it all works right
-
- SetWhenToDraw();
- return false;
- }
- }
-
-
- //=============================================================================
- // • MungeTitle [public, virtual]
- //=============================================================================
- // Munge the title to display the command key equiv appended to the control
- // title. This current will take "Fred" and make it "Fred cmd-F". Override
- // this routine to modify how the title is munged (prepend the key combo, don't
- // use a hyphen to save space, etc.)
-
- void
- HCmdButtonAttachment::MungeTitle(
- Uchar inHotKey )
- {
- LStr255 theTitle;
-
- GetOriginalTitle( theTitle ); // start with the original
- theTitle += char_Space; // add a space
- theTitle += char_Propeller; // add the command key
- theTitle += inHotKey; // and finally the given key
-
- // and set it internally
-
- SetMungedTitle( theTitle );
- }
-
-
- //=============================================================================
- // • FindHotKey [public, virtual]
- //=============================================================================
- // Based upon internal settings and configuration, determine the
- // magic key/character which we are to look for and act upon
-
- Uchar
- HCmdButtonAttachment::FindHotKey(
- Boolean inForceUpper )
- {
- Uchar theHotKey = 0;
-
- if ( GetControl() != nil ) {
- if ( GetUseSpecifiedKey() ) {
- theHotKey = GetHotKey();
- } else {
-
- // get the button's title
-
- Str255 theTitle;
- GetControl()->GetDescriptor(theTitle);
- theHotKey = theTitle[1];
- }
-
- // make sure the hot key char is uppercase, if desired
-
- if ( inForceUpper && ((theHotKey >= 'a') && (theHotKey <= 'z')) ) {
- ::UppercaseText( (Ptr)&theHotKey, 1, smSystemScript );
- }
- }
-
- return theHotKey;
- }
-
-
-
- // the following functions are declared inline in the header file. The #pragma
- // mark let's them show up in the CW IDE's function popup for ease of navigation
- // and reference. :-)
-
- #pragma mark HCmdButtonAttachment::GetControl
- #pragma mark HCmdButtonAttachment::SetControl
- #pragma mark HCmdButtonAttachment::GetControlPaneID
- #pragma mark HCmdButtonAttachment::SetControlPaneID
- #pragma mark HCmdButtonAttachment::GetDrawShortcut
- #pragma mark HCmdButtonAttachment::SetDrawShortcut
- #pragma mark HCmdButtonAttachment::GetUseSpecifiedKey
- #pragma mark HCmdButtonAttachment::SetUseSpecifiedKey
- #pragma mark HCmdButtonAttachment::GetUseFirstTitleChar
- #pragma mark HCmdButtonAttachment::SetUseFirstTitleChar
- #pragma mark HCmdButtonAttachment::GetHotKey
- #pragma mark HCmdButtonAttachment::SetHotKey
- #pragma mark HCmdButtonAttachment::GetShowKeyEquiv
- #pragma mark HCmdButtonAttachment::SetShowkeyEquiv
- #pragma mark HCmdButtonAttachment::GetOriginalTitle
- #pragma mark HCmdButtonAttachment::SetOriginalTitle
- #pragma mark HCmdButtonAttachment::GetMungedTitle
- #pragma mark HCmdButtonAttachment::SetMungedTitle
- #pragma mark HCmdButtonAttachment::GetDelay
- #pragma mark HCmdButtonAttachment::SetDelay
- #pragma mark HCmdButtonAttachment::GetWhenToDraw
- #pragma mark HCmdButtonAttachment::SetWhenToDraw